package net.fpeg.kotlin.msa.wordbase.service

import net.fpeg.kotlin.msa.wordbase.dao.WordDao
import net.fpeg.kotlin.msa.wordbase.dto.WordConditionDto
import net.fpeg.kotlin.msa.wordbase.dto.WordListDto
import net.fpeg.kotlin.msa.wordbase.dto.WordListIndexDto
import net.fpeg.kotlin.msa.wordbase.dao.WordSentenceDao
import net.fpeg.kotlin.msa.wordbase.entity.Word
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.support.PagedListHolder
import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Service


@Service
class WordListService {
    @Autowired
    lateinit var wordDao: WordDao

    @Autowired
    lateinit var wordSentenceDao: WordSentenceDao

    @Autowired
    lateinit var wordUserRelationService: WordUserRelationService

    @Autowired
    lateinit var wordSourceService: WordSourceService

    fun find(id: Long, pageable: Pageable) =
            wordDao.findDistinctByWordBases_WordUser_Id(id, pageable)


    fun find(userId: Long, wordConditionDto: WordConditionDto, pageable: Pageable): WordListDto {
        val cWord = wordConditionDto.wordValue.isNotEmpty();
        var cTag = wordConditionDto.tag
        if (wordConditionDto.wordTagValue == "无")
            cTag = false
        val cRelation = wordConditionDto.relation
        val cSource = wordConditionDto.source
        val cSubSource = wordConditionDto.subSource

        val tagValue = wordConditionDto.wordTagValue
        val wordValue = wordConditionDto.wordValue
        val sourceId = wordConditionDto.wordSourceId

        fun Set<Word>.getRelationWords() =
                wordUserRelationService
                        .fetchGroupIdByWordIn(userId, this)
                        .map {
                            wordUserRelationService
                                    .findTenseByGroupId(it ?: throw Exception("未知错误"))
                                    .map { it1 -> it1.word }
                                    .toSet()
                        }
                        .flatten()
                        .toSet()

        fun Set<Word>.getSentence() =
                when (cSubSource) {
                    true -> wordSourceService.findIds(sourceId)
                            .let { wordSentenceDao.findByIdIn(it) }
                    false -> wordSentenceDao.findByWordSource_Id(sourceId)
                }
                        .map { wordSentence ->
                            this.filter { word -> wordSentence.englishValue.contains(word.value) }
                        }
                        .flatten()
                        .toSet()

        return wordDao
                .run {
                    when {
                        !cWord && !cTag ->
                            findDistinctByWordBases_WordUser_Id(userId)
                        cWord && !cTag ->
                            findDistinctByWordBases_WordUser_IdAndValueContaining(userId, wordValue)
                        !cWord && cTag ->
                            findDistinctByWordBases_WordUser_IdAndWordBases_WordTag_Value(userId, tagValue)
                        cWord && cTag ->
                            findDistinctByWordBases_WordUser_IdAndValueContainingAndWordBases_WordTag_Value(userId, wordValue, tagValue)
                        else -> throw Exception("ca")
                    }
                }
                .run { if (cRelation) getRelationWords() else this }
                .run { if (cSource) getSentence() else this }
                .sortedWith(Comparator { a, b -> String.CASE_INSENSITIVE_ORDER.compare(a.value, b.value) })
                .map { WordListIndexDto(it.value) }
                .let {
                    PagedListHolder<WordListIndexDto>(it)
                            .apply {
                                pageSize = pageable.pageSize
                                page = pageable.pageNumber
                            }
                            .pageList
                            .let { pageList -> WordListDto(it.size, pageList) }
                }


//        var wordSet = when {
//            !cWord && !cTag && !cRelation && !cSource ->
//                wordDao.findDistinctByWordBases_WordUser_Id(userId)
//            cWord && !cTag && !cRelation && !cSource ->
//                wordDao.findDistinctByWordBases_WordUser_IdAndValueContaining(userId, wordValue)
//            !cWord && cTag && !cRelation && !cSource ->
//                wordDao.findDistinctByWordBases_WordUser_IdAndWordBases_WordTag_Value(userId, tagValue)
//            cWord && cTag && !cRelation && !cSource ->
//                wordDao.findDistinctByWordBases_WordUser_IdAndValueContainingAndWordBases_WordTag_Value(userId, wordValue, tagValue)
//            !cWord && !cTag && cRelation && !cSource ->
//                wordDao.findDistinctByWordBases_WordUser_Id(userId)
//                        .getRelationWords2()
//            cWord && !cTag && cRelation && !cSource ->
//                wordDao.findDistinctByWordBases_WordUser_IdAndValueContaining(userId, wordValue)
//                        .getRelationWords2()
//            !cWord && cTag && cRelation && !cSource ->
//                wordDao.findDistinctByWordBases_WordUser_IdAndWordBases_WordTag_Value(userId, tagValue)
//                        .getRelationWords2()
//            cWord && cTag && cRelation && !cSource ->
//                wordDao.findDistinctByWordBases_WordUser_IdAndValueContainingAndWordBases_WordTag_Value(userId, wordValue, tagValue)
//                        .getRelationWords2()
//            !cWord && !cTag && !cRelation && cSource ->
//                wordDao.findDistinctByWordBases_WordUser_Id(userId)
//                        .getSentence()
//            cWord && !cTag && !cRelation && cSource ->
//                wordDao.findDistinctByWordBases_WordUser_IdAndValueContaining(userId, wordValue)
//                        .getSentence()
//            !cWord && cTag && !cRelation && cSource ->
//                wordDao.findDistinctByWordBases_WordUser_IdAndWordBases_WordTag_Value(userId, tagValue)
//                        .getSentence()
//            cWord && cTag && !cRelation && cSource ->
//                wordDao.findDistinctByWordBases_WordUser_IdAndValueContainingAndWordBases_WordTag_Value(userId, wordValue, tagValue)
//                        .getSentence()
//            !cWord && !cTag && cRelation && cSource ->
//                wordDao.findDistinctByWordBases_WordUser_Id(userId)
//                        .getRelationWords2()
//                        .getSentence()
//            cWord && !cTag && cRelation && cSource ->
//                wordDao.findDistinctByWordBases_WordUser_IdAndValueContaining(userId, wordValue)
//                        .getRelationWords2()
//                        .getSentence()
//            !cWord && cTag && cRelation && cSource ->
//                wordDao.findDistinctByWordBases_WordUser_IdAndWordBases_WordTag_Value(userId, tagValue)
//                        .getRelationWords2()
//                        .getSentence()
//            cWord && cTag && cRelation && cSource ->
//                wordDao.findDistinctByWordBases_WordUser_IdAndValueContainingAndWordBases_WordTag_Value(userId, wordValue, tagValue)
//                        .getRelationWords2()
//                        .getSentence()


    }
}
